﻿using Freshbox2._0.DAL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Freshbox2._0.BLL
{
    public class BaseBll<T> where T : class
    {
        public virtual BaseDal<T> dal { get; set; }

        public int Add(T model)
        {
            return dal.Add(model);
        }


        public int Delete(T model)
        {
            return dal.Delete(model);
        }

        public int Delete(Func<T, bool> condition)
        {
            return dal.Delete(condition);
        }


        public int Modify(T model)
        {
            return dal.Modify(model);
        }


        public IQueryable<T> Search()
        {
            return dal.Search();
        }

        public IQueryable<T> Search(Expression<Func<T, bool>> condition)
        {
            return dal.Search(condition);
        }

        public IQueryable<T> Search<S>(Expression<Func<T, bool>> condition, Expression<Func<T, S>> order, bool isAsc)
        {
            return dal.Search<S>(condition, order, isAsc);
        }

        public IQueryable<T> Search<S>(Expression<Func<T, bool>> condition, bool isAsc, Expression<Func<T, S>> order, int pageSize, int pageIndex, out int count)
        {
            return dal.Search<S>(condition, isAsc, order, pageSize, pageIndex, out count);
        }

        public virtual IQueryable<T> Search<S>(T model, Expression<Func<T, bool>> condition, bool isAsc, Expression<Func<T, S>> order, int pageSize, int pageIndex, out int count)
        {

            Expression<Func<T, bool>> where;
            Type t = model.GetType();
            PropertyInfo[] properties = t.GetProperties();
            ParameterExpression param = Expression.Parameter(typeof(T), "x");
            BinaryExpression be = Expression.Equal(Expression.Constant(1), Expression.Constant(1));
            foreach (PropertyInfo pInfo in properties)
            {
                object val = pInfo.GetValue(model, null);
                if ((pInfo.PropertyType == typeof(int) && (int)val != 0) || (pInfo.PropertyType == typeof(string) && (string)val != null) || (pInfo.PropertyType == typeof(Nullable<int>) && (Nullable<int>)val != null))
                {
                    MemberExpression left = Expression.Property(param, pInfo);
                    ConstantExpression right = Expression.Constant(val, left.Type);
                    if (pInfo.PropertyType == typeof(string))
                    {
                        MethodCallExpression methodExpression = Expression.Call(left, typeof(string).GetMethod("Contains"), right);
                        be = Expression.And(be, methodExpression);
                    }
                    else
                    {
                        be = Expression.And(be, Expression.Equal(left, right));
                    }
                }

            }
            where = Expression.Lambda<Func<T, bool>>(be, param);

            return dal.Search<S>(where, isAsc, order, pageSize, pageIndex, out count);
        }


        public IQueryable<S> SearchBySQL<S>(string sql)
        {
            return dal.SearchBySQL<S>(sql);
        }
    }
}
